import axios from 'axios';
import Vue from 'vue';
// import { Toast } from 'vant';
import store from '@/store';
import router from '@/router';
import JSONbig from 'json-bigint';

// const isLocal = window.location.hostname === 'localhost';

export const req = axios.create({
    timeout: 15000,
    transformResponse: [function (data) {
        try {
            return JSONbig.parse(data);
        } catch (err) {
            // console.log('转换失败', err);
            return data;
        }
    }]
});

const refreshTokenReq = axios.create({ // 专用于刷新 token 的请求，若服用原来的请求会导致使用错误的 token 导致刷新 token 失败
    timeout: 15000
});

req.defaults.headers.post['Content-Type'] = 'application/json';
req.interceptors.request.use(config => {
    const { user } = store.state;
    if (user) {
        config.headers.Authorization = `Bearer ${user.token}`;
    }
    // 在发送请求之前做些什么   config 就是构建完成的 axios 请求体
    return config;
}, err => {
    return Promise.reject(err);
});
req.interceptors.response.use(res => {
    return res;
}, catchErr);

export const getConfig = async () => {
    // 获取本地或者configmap配置文件的kc和请求json
    const baseUrl = window.location.origin;
    const config = await axios({
        url: `${baseUrl}/config.json`
    });
    if (config.data) return config.data;
};

const devopsInfo = async (req, url, method = 'get', arg) => {
    const info = await req({
        method,
        url,
        ...arg
    });
    return info;
};

export const reqDev = async (url, method = 'get', arg) => {
    const preUrl = window.baseUrl;
    const prePort = window.basePort;
    const extra = window.extra;
    const path = `${preUrl}:${prePort}/${extra}`;
    const baseUrl = path + url;
    // const baseUrl = isLocal ? '/api' + url : path + '/api/v2/fin' + url;
    const info = await devopsInfo(req, baseUrl, method, arg);
    // const diyCode = [];
    // if (info.data.errorCode && !diyCode.includes(info.data.errorCode)) {
    //     Vue.prototype.$Message.error(info.data.errorInfo || '操作失败，请稍后再试');
    // }
    return info.data;
};

async function catchErr (err) {
    // 处理公共请求的异常提示
    // console.log(err);
    let status = err.response ? err.response.status : null;
    if (!status) Vue.prototype.$toast.fail('网络错误，请求超时，请稍后再试');
    if (status === 400) Vue.prototype.$toast.fail('请求参数错误');
    else if (status === 401) { // token 无效
        let { user } = store.state;
        if (!user || !user.token) return redirectLogin(); // 不存在 user 或 user.token 的时候，直接跳转到登入页
        try {
            const res = await refreshTokenReq({ // 使用已有的 refresh_token 去刷新 token
                url: `${window.baseUrl}:${window.basePort}/${window.extra}/v1_0/authorizations`,
                method: 'put',
                headers: {
                    'Content-Type': 'application/json',
                    Authorization: `Bearer ${user.refresh_token}`
                }
            });
            if (res.data.message === 'OK') { // 刷新成功时，更新 user 以及 localStorage 里面的 token 并重新发送失败的请求
                user.token = res.data.data.token;
                store.dispatch('updateUser', user);
                return req(err.config);
            }
        } catch (err) { // 刷新失败时，跳转到登入页
            redirectLogin();
        }
    } else if (status === 403) Vue.prototype.$toast.fail('没有权限操作');
    else if (status >= 500) Vue.prototype.$toast.fail('服务器异常，请稍后再试');
    return Promise.reject(err);
}

function redirectLogin () {
    router.replace({
        name: 'login',
        query: {
            redirect: router.currentRoute.fullPath
        }
    }); // 使用 replace 在效果上和 push 一样都会使 url 发生变化，但是 replace 不会添加历史记录
}
